package impl

import (
	"context"
	"errors"
	"fmt"
	"go-caipu/pkg/infra/log"
	"go-caipu/pkg/services/admin/systemlog"
	"go-caipu/pkg/services/admin/systemlog/models"
	"go-caipu/pkg/services/dto"
	"gorm.io/gorm"
	"time"
)

type store interface {
	GetSysLoginLogPage(ctx context.Context, cmd systemlog.GetSysLoginLogPageCommand) (data []systemlog.SysLoginLog, num int64, err error)
	Get(ctx context.Context, cmd systemlog.GetSysLoginLogCommand) (systemlog.SysLoginLog, error)
	InsertLoginLog(ctx context.Context, post *systemlog.SysLoginLog) error
	Update(ctx context.Context, post systemlog.SysLoginLog) error
	Remove(ctx context.Context, cmd systemlog.RemoveSysLoginLogCommand) error

	GetSysOperaLogPage(ctx context.Context, cmd systemlog.GetSysOperaLogPageCommand) (data []systemlog.SysOperaLog, num int64, err error)
	GetSysOperaLog(ctx context.Context, cmd systemlog.GetSysOperaLogCommand) (systemlog.SysOperaLog, error)
	InsertOperLog(ctx context.Context, post *systemlog.SysOperaLog) error
}
type sqlStore struct {
	db     *gorm.DB
	logger log.Logger
}

func ProvideStore(db *gorm.DB) sqlStore {
	return sqlStore{
		db:     db,
		logger: log.New("dept.store"),
	}
}

func (s sqlStore) GetSysLoginLogPage(ctx context.Context, cmd systemlog.GetSysLoginLogPageCommand) (result []systemlog.SysLoginLog, num int64, err error) {
	var items []models.SysLoginLog
	err = s.db.Model(&models.SysLoginLog{}).Scopes(
		dto.MakeCondition(cmd.GetNeedSearch()),
		dto.Paginate(cmd.GetPageSize(), cmd.GetPageIndex()),
	).Order("login_time desc").Find(&items).Limit(-1).Offset(-1).Count(&num).Error
	if err != nil {
		return
	}
	for _, v := range items {
		result = append(result, ConvertToDTO(v))
	}
	return
}
func ConvertToDTO(model models.SysLoginLog) systemlog.SysLoginLog {
	result := systemlog.SysLoginLog{
		Id:            model.Id,
		Username:      model.Username,
		Status:        model.Status,
		Ipaddr:        model.Ipaddr,
		LoginLocation: model.LoginLocation,
		Browser:       model.Browser,
		Os:            model.Os,
		Platform:      model.Platform,
		LoginTime:     model.LoginTime.Format("2006-01-02 15:04:05"),
		Remark:        model.Remark,
		Msg:           model.Msg,
		ControlBy:     model.ControlBy,
	}
	return result
}
func (s sqlStore) Get(ctx context.Context, cmd systemlog.GetSysLoginLogCommand) (result systemlog.SysLoginLog, err error) {
	var data models.SysLoginLog
	err = s.db.Model(&data).First(&data, cmd.Id).Error
	if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
		err = errors.New(fmt.Sprintf("Id=%d record Not found", cmd.Id))
		return
	}
	if err != nil {
		s.logger.Log(fmt.Sprintf("get  loginlog=%d  error:%s", cmd.Id, err.Error()))
		return
	}
	return ConvertToDTO(data), nil
}
func ConvertToDT(model *systemlog.SysLoginLog, cmd *models.SysLoginLog) {
	cmd.Id = model.Id
	cmd.Username = model.Username
	cmd.Status = model.Status
	cmd.Ipaddr = model.Ipaddr
	cmd.LoginLocation = model.LoginLocation
	cmd.Browser = model.Browser
	cmd.Os = model.Os
	cmd.Platform = model.Platform
	cmd.LoginTime = time.Now()
	cmd.Remark = model.Remark
	cmd.Msg = model.Msg
}

func (s sqlStore) InsertLoginLog(ctx context.Context, cmd *systemlog.SysLoginLog) (err error) {
	tx := s.db.Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()
	var data models.SysLoginLog
	ConvertToDT(cmd, &data)
	data.CreatedAt = time.Now()
	data.CreateBy = cmd.CreateBy

	err = tx.Create(&data).Error
	if err != nil {
		s.logger.Log(fmt.Sprintf("insert  loginlog  error:%s", err.Error()))
		return err
	}
	return nil
}

func (s sqlStore) Update(ctx context.Context, cmd systemlog.SysLoginLog) (err error) {
	tx := s.db.Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()
	//查询当前部门名称是否存在
	var data models.SysLoginLog
	err = s.db.Model(&data).First(&data, cmd.Id).Error
	if err != nil {
		s.logger.Log(fmt.Sprintf("check SysLoginLog id=%d is exists error:%s", cmd.Id, err.Error()))
		return err
	}
	ConvertToDT(&cmd, &data)
	data.UpdatedAt = time.Now()
	data.UpdateBy = cmd.UpdateBy
	err = tx.Save(&data).Error
	if err != nil {
		s.logger.Log(fmt.Sprintf("update  loginlog  error:%s", err.Error()))
		return err
	}
	return nil
}

func (s sqlStore) Remove(ctx context.Context, cmd systemlog.RemoveSysLoginLogCommand) (err error) {
	tx := s.db.Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()
	var data models.SysLoginLog
	err = tx.Model(&models.SysLoginLog{}).Delete(&data, cmd.Ids).Error
	if err != nil {
		return err
	}
	return
}
